/*
 * 系统工具类
 */
// 效率高，耗费内存大，克隆大对象可能会内存溢出
let util = {
    clone: function(target) {
        if (typeof target == 'object') {
            let result = Array.isArray(target) ? [] : {};
            for (let key in target) {
                if (typeof target[key] == 'object') {
                    result[key] = this.clone(target[key]);
                } else {
                    result[key] = target[key];
                }
            }
            return result;
        }
        return target;
    },
    clone2: function(target) {
        let parentList = [];
        let keyList = [];
        let resultList = [];
        let level = 0;
        let result = null;
        if (target instanceof Array || target instanceof Object) {
            if (target instanceof Array) {
                result = [];
            } else if (target instanceof Object) {
                result = {};
            }
            parentList.push(target);
            resultList.push(result);
            keyList.push(null);
            while (true) {
                let read0 = keyList[level] == null;
                let read1 = keyList[level] == null;
                let up = true;
                for (let i in parentList[level]) {
                    if (keyList[level] == i) {
                        read0 = true;
                    } else if (read0) {
                        read1 = true;
                    }
                    if (read1) {
                        let item = parentList[level][i];
                        if (item instanceof Array || item instanceof Object) {
                            parentList[level + 1] = item;
                            if (item instanceof Array) {
                                resultList[level + 1] = [];
                            } else if (item instanceof Object) {
                                resultList[level + 1] = {};
                            }
                            keyList[level] = i;
                            keyList[level + i] = null;
                            level++;
                            up = false;
                            break;
                        } else {
                            resultList[level][i] = item;
                        }
                    }
                }
                if (up) {
                    if (level > 0) {
                        resultList[level - 1][keyList[level - 1]] = resultList[level];
                    }
                    if (level < 1) {
                        break;
                    } else {
                        parentList.splice(level, 1);
                        resultList.splice(level, 1);
                        level -= 1;
                    }
                }
            }
        } else {
            result = target;
        }
        return result;
    },
    getID: function() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
            let  r = (Math.random() * 16) | 0,
                v = c == 'x' ? r : (r & 0x3) | 0x8
            return v.toString(16);
        });
    },
    getProjectName: function() {
        let pathName = window.document.location.pathname;
        let projectName = pathName.substring(0, pathName.substring(1).indexOf('/') + 1);
        return '/' + projectName;
    },
    toInteger: function(num) {
        let n = parseInt(Number(num).toFixed(0));
        return n;
    },
    toDouble2: function(num) {
        let n = parseFloat(Number(num).toFixed(2));
        return n;
    },
    toDouble3: function(num) {
        let n = parseFloat(Number(num).toFixed(3));
        return n;
    },
    isNotBlank: function(object) {
        return object !== undefined && object !== null && object !== '';
    },
    isBlank: function(object) {
        return object === undefined || object === null || object === '';
    },
    isNumber: function(object) {
        if (this.isNotBlank(object)) {
            try {
                let num = Number(object);
                if (isNaN(num)) {
                    return false;
                } else {
                    return true;
                }
            } catch (e) {
                return false;
            }
        } else {
            return false;
        }
    },
    rotateCoordinate: function(point, center, rotate) {
        return {
            x: (point.x - center.x) * Math.cos(rotate * Math.PI / 180) - (point.y - center.y) * Math.sin(rotate * Math.PI / 180) + center.x,
            y: (point.x - center.x) * Math.sin(rotate * Math.PI / 180) + (point.y - center.y) * Math.cos(rotate * Math.PI / 180) + center.y,
        }
    },
    getCenterPoint: function(p1, p2) {
        return {
            x: p1.x + ((p2.x - p1.x) / 2),
            y: p1.y + ((p2.y - p1.y) / 2),
        }
    },
    translateWholeTurn: function(deg) {
        return (deg + 360) % 360
    },
    getColor: function(start, end, num) {
        start = start.replace('#', '');
        end = end.replace('#', '');
        let ls = [];
        if (num > 2) {
            let start_r = parseInt(start.substring(0, 2), 16);
            let start_g = parseInt(start.substring(2, 4), 16);
            let start_b = parseInt(start.substring(4, 6), 16);
            let end_r = parseInt(end.substring(0, 2), 16);
            let end_g = parseInt(end.substring(2, 4), 16);
            let end_b = parseInt(end.substring(4, 6), 16);
            let step_r = (end_r - start_r) / num;
            let step_g = (end_g - start_g) / num;
            let step_b = (end_b - start_b) / num;
            for (let i = 0; i < num; i++) {
                let r = parseInt(step_r * i + start_r).toString(16);
                let g = parseInt(step_g * i + start_g).toString(16);
                let b = parseInt(step_b * i + start_b).toString(16);
                if (r.length < 2) {
                    r = '0' + r;
                }
                if (g.length < 2) {
                    g = '0' + g;
                }
                if (b.length < 2) {
                    b = '0' + b;
                }
                ls.push('#' + r + g + b);
            }
        } else {
            ls.push('#' + start.toString(16));
            ls.push('#' + end.toString(16));
        }
        return ls;
    },
    numberToTime(timestamp, length = 19) {
        let date = new Date(timestamp);
        let strDate = '';
        let Y = date.getFullYear();
        strDate += Y;
        if (length > 4) {
            strDate += '-';
            let M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1 );
            strDate += M;
            if (length > 7) {
                strDate += '-';
                let D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate());
                strDate += D;
                if (length > 10) {
                    strDate += ' ';
                    let h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours());
                    strDate += h;
                    if (length > 13) {
                        strDate += ':';
                        let m = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes());
                        strDate += m;
                        if (length > 16) {
                            strDate += ':';
                            let s = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds());
                            strDate += s;
                            if (length > 19) {
                                strDate += '.';
                                let ss = date.getMilliseconds();
                                if (ss < 10) {
                                    ss = '00' + ss;
                                } else if (ss < 100) {
                                    ss = '0' + ss;
                                }
                                strDate += ss;
                            }
                        }
                    }
                }
            }
        }
        return strDate;
    },
    getElementBox: function(element) {// 获得组件真正包围盒
        let box = {
            left: element.style.left.pixel,
            top: element.style.top.pixel,
            right: element.style.left.pixel + element.style.width.pixel + 1,
            bottom: element.style.top.pixel + element.style.height.pixel + 1
        };
        if (element.style.rotate != 0) {
            let center = {
                x: (box.left + box.right) / 2,
                y: (box.top + box.bottom) / 2
            };
            let pointList = [];
            pointList[0] = util.rotateCoordinate({ x: box.left, y: box.top }, center, element.style.rotate);
            pointList[1] = util.rotateCoordinate({ x: box.right, y: box.top }, center, element.style.rotate);
            pointList[2] = util.rotateCoordinate({ x: box.right, y: box.bottom }, center, element.style.rotate);
            pointList[3] = util.rotateCoordinate({ x: box.left, y: box.bottom }, center, element.style.rotate);
            let left = Number.MAX_VALUE;
            let top = Number.MAX_VALUE;
            let right = -Number.MAX_VALUE;
            let bottom = -Number.MAX_VALUE;
            for (let i = 0; i < pointList.length; i ++) {
                let point = pointList[i];
                if (point.x < left) {
                    left = point.x;
                }
                if (point.x > right) {
                    right = point.x;
                }
                if (point.y < top) {
                    top = point.y;
                }
                if (point.y > bottom) {
                    bottom = point.y;
                }
            }
            box.left = util.toInteger(left);
            box.top = util.toInteger(top);
            box.right = util.toInteger(right);
            box.bottom = util.toInteger(bottom);
        }
        return box;
    },
    getElementBoxList: function(elementList) {
        let list = [];
        for (let i = 0; i < elementList.length; i ++) {
            let box = this.getElementBox(elementList[i]);
            list.push(box);
        }
        return list;
    },
    replaceMinus: function(string) {
        return string.replace(/-/g, '');
    },
    rgbaToHexColor: function(rgbaColor, alphaMaxVal = 1) {
        if (rgbaColor) {
            if (/^(rgb|RGB)/.test(rgbaColor)) {
                let rgbaArray = [];
                if (rgbaColor.indexOf('rgba') === 0) {
                    rgbaArray = rgbaColor.replace(/(?:\(|\)|rgba|RGBA)*/g, '').split(',').map(value => +value);
                } else {
                    rgbaArray = rgbaColor.replace(/(?:\(|\)|rgb|RGB)*/g, '').split(',').map(value => +value);
                }
                return '#' + rgbaArray.map((chanel, index) => {
                  let hexNum = '';
                  if (index === 3) {
                    hexNum = Number(Math.round(chanel * 255 / alphaMaxVal)).toString(16).toUpperCase();
                  } else {
                    hexNum = Number(chanel).toString(16).toUpperCase();
                  }
                  return hexNum.length===1 ? '0' + hexNum : hexNum;
                }).join('');
            } else {
                return rgbaColor;
            }
        } else {
            return '#FFFFFF00';
        }
    },
    debounce: function(fn, t) {
        const delay = t || 100;
        let timer = null;
        return function() {
            const args = arguments;
            const context = this;
            if (timer) {
                clearTimeout(timer);
            }
            timer = setTimeout(() => {
                timer = null;
                fn.apply(context, args);
            }, delay);
        };
    },
    base64ToFile: function(data, filename) {
        let arr = data.split(','), mime = arr[0].match(/:(.*?);/)[1];
        let bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
        while (n--) {
            u8arr[n] = bstr.charCodeAt(n);
        }
        return new File([u8arr], filename, { type: mime });
    },
    getUrlParam: function(name) {
        let reg = new RegExp('(\\?|\&)' + name + '=([^&]*)(\&|$)', 'i');
        let r = window.location.href.match(reg);
        if (r != null) return unescape(r[2]); return null;
    }
};
export default util;